package com.chenl.provider.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;

@Slf4j
@Component
public class FileUtils {
    public static void main(String[] args) throws Exception {
        String sourceUrl="http://sxszty-test.onesport.com.cn/static_access/1e270f12b2994db69f432d2cf64092e7.p12";
        String outherUrl="D:/data2/dad.p12";
        InputStream inputStream = getInputStreamFromUrl(sourceUrl);
        outPutByInputstreamOriginal(inputStream,"D:/data/d.p12");
    }

    /**
     * 上传指定文件到路径下,linux可用
     * @param file  文件 MultipartFile
     * @param
     * @throws Exception
     */
    public static void uploadByMultipartFile(MultipartFile file,String dirPath, String fileName) throws Exception {
        createDirectory(dirPath);
        outPutByInputstreamOriginal(file.getInputStream(),dirPath+"/"+fileName);
    }

    /**
     * win可用，linux上暂不可用，待完善
     * 将InputStream输出到指定的路径下(基于Resources)
     * @param file:文件
     * @param path:目标路径地址,带文件名(基于Resources)
     * @throws IOException
     */
    public  void outPutByMultFile(MultipartFile file, String path) throws Exception {
        ApplicationHome applicationHome=new ApplicationHome(this.getClass());
        String pathStr = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath()+"/src/main/resources"+path;
        outPutByInputstreamOriginal(file.getInputStream(),pathStr);
    }

    /**
     * InputStream转为Byte数组
     * @param inputStream:输入流
     */
    public static byte[] inputStreamToByte(InputStream inputStream) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int index = -1;
        while((index = inputStream.read()) != -1){
            baos.write(index);
        }
        byte[] bytes = baos.toByteArray();
        return bytes;
    }

    /**
     * 将字节数组输出到指定的路径下(可以和inputStreamToByte组合,从一个File读到另一个File)
     * @param bytes:字节数组
     * @param path:目标路径地址
     */
    public static void outPutByBytes(byte[] bytes,String path){
        IoUtil.write(FileUtil.getOutputStream(path),true,bytes);
    }

    /**
     * 将InputStream输出到指定的路径下
     * @param inputStream:输入流
     * @param path:目标路径地址
     * @throws IOException
     */
    public static void outPutByInputstream(InputStream inputStream,String path) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int index = -1;
        while((index = inputStream.read()) != -1){
            baos.write(index);
        }
        byte[] bytes = baos.toByteArray();
        IoUtil.write(FileUtil.getOutputStream(path),true,bytes);
    }
    public static void outPutByInputstreamOriginal(InputStream inputStream, String path) throws Exception {
        BufferedInputStream bif=new BufferedInputStream(inputStream);
        OutputStream ot=null;
        try {
            ot = new BufferedOutputStream(Files.newOutputStream(Paths.get(path)));
            byte[] buffer = new byte[1024];
            int len;
            while ((-1 != (len = bif.read(buffer)))) {
                ot.write(buffer, 0, len);
            }
        }catch (Exception e){
            log.error(e.getMessage(), e);
            throw new Exception("文件存储到磁盘失败");
        }finally {
            if (Objects.nonNull(ot)) {
                ot.close();
            }
        }
    }


    /**
     * 从URL读取文件拷贝文件输出到指定路径下(路径统一传左斜杠)
     * @param sourceUrl:数据源URL地址 如: http://sxszty-test.onesport.com.cn/static_access/1e270f12b2994db69f432d2cf64092e7.p12
     * @param otherUrl:目标路径地址  如:  D:/data/dad.p12
     * @throws IOException
     */
    public static void copyFileToOther(String sourceUrl,String otherUrl) throws IOException {
        //使用前先创建上级文件夹
        if (otherUrl.contains("/")){
            int i = otherUrl.lastIndexOf("/");
            String substring = otherUrl.substring(0, i);
            File file = new File(substring);
            if(!file.exists()){
                file.mkdirs();
            }
        }
        File file = new File(otherUrl);
        org.apache.commons.io.FileUtils.copyURLToFile(new URL(sourceUrl),file);
    }
    /**
     * 根据url下载返回文件流InputStream
     * @param urlStr
     * @return
     */
    public static InputStream getInputStreamFromUrl(String urlStr) {
        InputStream inputStream=null;

        try {
            //url解码
            URL url = new URL(java.net.URLDecoder.decode(urlStr, "UTF-8"));
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置超时间为3秒
            conn.setConnectTimeout(3 * 1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            inputStream = conn.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return inputStream;
    }


    /**
     * 读文件并输出
     * @param filePath
     * @return
     * @throws IOException
     */
    public static String readTxtFile(String filePath) throws IOException {
        // 第一步：建立连接关系
        File file = new File(filePath);
        // 第二步：获取输入流
        FileInputStream stream = new FileInputStream(file);
        // 第三步：读取输入流
        InputStreamReader inputStreamReader = new InputStreamReader(stream);
        // 第四步：将流写进StringBuffer中，输出
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String line = null ;
        StringBuilder strBuilder = new StringBuilder();
        while ((line = bufferedReader.readLine()) != null){
            strBuilder.append(line).append("\r\n");
        }
        // 第五步：关流
        bufferedReader.close();
        inputStreamReader.close();
        stream.close();
        // 返回
        return strBuilder.toString();
    }

    /**
     * 判断文件夹是否存在，如果不存在创建它
     *
     * @param dirPath 文件夹路径
     * @return 是否创建成功
     */
    public static void createDirectory(String dirPath) {
        try {
            File file = new File(dirPath);
            if (!file.exists()) {
                // 如果目录不存在，则创建目录
                if (file.mkdirs()) {
                    log.info("目录创建成功：" + dirPath);
                } else {
                    log.info("目录创建失败：" + dirPath);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("目录创建失败:"+e.toString());
        }
    }
}
